Skip to content

Conversation

@icecrasher321
Copy link
Collaborator

Summary

Collaborative add made edge validation skipping possible which led to incorrect edges. Store level checks continue to handle broadcasts / copilot edits.

Type of Change

  • Bug fix

Testing

Tested manually

Checklist

  • Code follows project style guidelines
  • Self-reviewed my changes
  • Tests added/updated and passing
  • No new warnings introduced
  • I confirm that I have read and agree to the terms outlined in the Contributor License Agreement (CLA)

@vercel
Copy link

vercel bot commented Jan 24, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Review Updated (UTC)
docs Skipped Skipped Jan 24, 2026 9:06pm

Request Review

@greptile-apps
Copy link
Contributor

greptile-apps bot commented Jan 24, 2026

Greptile Summary

This PR fixes a race condition in collaborative edge validation by ensuring consistent validation at the collaborative layer before operations are queued and broadcast to other clients. Previously, edge validation could be skipped during collaborative adds, allowing invalid edges (targeting trigger blocks) to be synced across clients. The fix moves edge validation to the hook layer, passes validated edges through the operation queue, and adds skipValidation/skipEdgeValidation options to store methods to prevent double validation.

  • Moved filterValidEdges to utils: Extracted edge validation logic from workflow store to reusable utility for consistent validation across layers
  • Added validation skip options: Both batchAddEdges (skipValidation) and batchAddBlocks (skipEdgeValidation) now support skipping validation when already performed upstream
  • Fixed collaborativeBatchAddEdges: Now validates edges with filterValidEdges before queueing to prevent invalid edges from syncing
  • Fixed collaborativeBatchAddBlocks: Validates edges by combining existing and new blocks for complete validation context, preventing orphaned edge references
  • Improved logging: Added edge filtering metrics to track invalid edges being filtered out

Confidence Score: 3/5

  • PR has some inconsistencies in edge validation between local and remote paths that may leave the system vulnerable to race conditions in certain scenarios.
  • The PR correctly fixes the race condition for local collaborative adds by validating edges before broadcast. However, the remote edge-add handler (line 226-235) only applies filterNewEdges without filterValidEdges, which could allow invalid edges to be accepted from other clients. The PR description mentions "Store level checks continue to handle broadcasts / copilot edits" but this creates an asymmetry: local operations are validated at the hook layer before broadcast, while remote operations rely on eventual store-level validation. This inconsistency reduces confidence because: (1) there's a window where invalid edges could exist in local state if coming from remote, (2) the validation logic isn't consistently applied across both paths, and (3) this could lead to different behavior for users on different clients. While the primary race condition may be addressed, the implementation could be more robust.
  • apps/sim/hooks/use-collaborative-workflow.ts - Remote edge handling at BATCH_ADD_EDGES should apply same validation as local path for consistency

Important Files Changed

Filename Overview
apps/sim/stores/workflows/utils.ts Added exported filterValidEdges function and supporting isValidEdge helper. This function validates edges by checking that source and target blocks exist, are not annotation-only, and target is not a trigger block. Properly separated from workflow store for reusability in collaborative workflows.
apps/sim/stores/workflows/workflow/store.ts Removed duplicate isValidEdge and filterValidEdges functions and moved import to utils. Added skipEdgeValidation option to batchAddBlocks and skipValidation option to batchAddEdges to allow callers to skip validation when already performed at a higher level. This prevents double validation and race conditions during collaborative adds.
apps/sim/stores/workflows/workflow/types.ts Updated batchAddBlocks signature to include options?: { skipEdgeValidation?: boolean } parameter and batchAddEdges to include options?: { skipValidation?: boolean } parameter. Type signatures now match implementation.
apps/sim/hooks/use-collaborative-workflow.ts Fixed race condition by validating edges before queueing operations in collaborativeBatchAddEdges and collaborativeBatchAddBlocks. Now consistently applies filterValidEdges validation at the collaborative layer, preventing invalid edges from being broadcast to other clients. Passes validated edges with skip flags to store methods to avoid double validation.

Sequence Diagram

sequenceDiagram
    participant User1 as Client A (Local User)
    participant Collab as Collaborative Hook
    participant Store as Workflow Store
    participant Queue as Operation Queue
    participant Server as Server/Socket
    participant User2 as Client B (Remote User)

    Note over User1,User2: Before Fix: Race Condition Scenario
    User1->>Collab: addEdges (invalid edge targeting trigger)
    Collab->>Queue: Add to queue without validation
    Queue->>Server: Broadcast BATCH_ADD_EDGES (invalid edge)
    Server->>User2: Receive edges
    User2->>Store: Apply edges (may accept if store validation delayed)
    Note over User2: Invalid edge accepted due to timing

    Note over User1,User2: After Fix: Consistent Validation
    User1->>Collab: addEdges
    Collab->>Collab: filterValidEdges (validate edges)
    Collab->>Store: batchAddEdges with skipValidation=true
    Collab->>Queue: Queue validated edges only
    Queue->>Server: Broadcast BATCH_ADD_EDGES (only valid edges)
    Server->>User2: Receive edges
    User2->>Collab: Receive operation
    Collab->>Store: filterNewEdges + batchAddEdges
    Note over User2: Filtered then stored (but missing filterValidEdges check)
Loading

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Additional Comments (1)

  1. apps/sim/hooks/use-collaborative-workflow.ts, line 226-235 (link)

    logic: When receiving remote BATCH_ADD_EDGES, the code applies filterNewEdges but doesn't apply filterValidEdges. This means remote clients can still broadcast invalid edges that pass the filterNewEdges check (which only checks for duplicates and self-loops), potentially reintroducing the race condition this PR fixes. The store-level checks continue as mentioned in the PR description, but for consistency with the local collaborativeBatchAddEdges method, consider also validating with filterValidEdges here.

4 files reviewed, 1 comment

Edit Code Review Agent Settings | Greptile

@icecrasher321
Copy link
Collaborator Author

@cursor review

Copy link

@cursor cursor bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

@waleedlatif1 waleedlatif1 merged commit 841cb63 into staging Jan 24, 2026
11 checks passed
waleedlatif1 added a commit that referenced this pull request Jan 24, 2026
…2973)

* fix(subflows): tag dropdown + resolution logic (#2949)

* fix(subflows): tag dropdown + resolution logic

* fixes;

* revert parallel change

* chore(deps): bump posthog-js to 1.334.1 (#2948)

* fix(idempotency): add conflict target to atomicallyClaimDb query + remove redundant db namespace tracking (#2950)

* fix(idempotency): add conflict target to atomicallyClaimDb query

* delete needs to account for namespace

* simplify namespace filtering logic

* fix cleanup

* consistent target

* improvement(kb): add document filtering, select all, and React Query migration (#2951)

* improvement(kb): add document filtering, select all, and React Query migration

* test(kb): update tests for enabledFilter and removed userId params

* fix(kb): remove non-null assertion, add explicit guard

* improvement(logs): trace span, details (#2952)

* improvement(action-bar): ordering

* improvement(logs): details, trace span

* feat(blog): v0.5 release post (#2953)

* feat(blog): v0.5 post

* improvement(blog): simplify title and remove code block header

- Simplified blog title from "Introducing Sim Studio v0.5" to "Introducing Sim v0.5"
- Removed language label header and copy button from code blocks for cleaner appearance

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* ack PR comments

* small styling improvements

* created system to create post-specific components

* updated componnet

* cache invalidation

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* feat(admin): add credits endpoint to issue credits to users (#2954)

* feat(admin): add credits endpoint to issue credits to users

* fix(admin): use existing credit functions and handle enterprise seats

* fix(admin): reject NaN and Infinity in amount validation

* styling

* fix(admin): validate userId and email are strings

* improvement(copilot): fast mode, subagent tool responses and allow preferences (#2955)

* Improvements

* Fix actions mapping

* Remove console logs

* fix(billing): handle missing userStats and prevent crashes (#2956)

* fix(billing): handle missing userStats and prevent crashes

* fix(billing): correct import path for getFilledPillColor

* fix(billing): add Number.isFinite check to lastPeriodCost

* fix(logs): refresh logic to refresh logs details (#2958)

* fix(security): add authentication and input validation to API routes (#2959)

* fix(security): add authentication and input validation to API routes

* moved utils

* remove extraneous commetns

* removed unused dep

* improvement(helm): add internal ingress support and same-host path consolidation (#2960)

* improvement(helm): add internal ingress support and same-host path consolidation

* improvement(helm): clean up ingress template comments

Simplify verbose inline Helm comments and section dividers to match the
minimal style used in services.yaml.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(helm): add missing copilot path consolidation for realtime host

When copilot.host equals realtime.host but differs from app.host,
copilot paths were not being routed. Added logic to consolidate
copilot paths into the realtime rule for this scenario.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* improvement(helm): follow ingress best practices

- Remove orphan comments that appeared when services were disabled
- Add documentation about path ordering requirements
- Paths rendered in order: realtime, copilot, app (specific before catch-all)
- Clean template output matching industry Helm chart standards

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* feat(blog): enterprise post (#2961)

* feat(blog): enterprise post

* added more images, styling

* more content

* updated v0-5 post

* remove unused transition

---------

Co-authored-by: Vikhyath Mondreti <vikhyath@simstudio.ai>

* fix(envvars): resolution standardized (#2957)

* fix(envvars): resolution standardized

* remove comments

* address bugbot

* fix highlighting for env vars

* remove comments

* address greptile

* address bugbot

* fix(copilot): mask credentials fix (#2963)

* Fix copilot masking

* Clean up

* Lint

* improvement(webhooks): remove dead code (#2965)

* fix(webhooks): subscription recreation path

* improvement(webhooks): remove dead code

* fix tests

* address bugbot comments

* fix restoration edge case

* fix more edge cases

* address bugbot comments

* fix gmail polling

* add warnings for UI indication for credential sets

* fix(preview): subblock values (#2969)

* fix(child-workflow): nested spans handoff (#2966)

* fix(child-workflow): nested spans handoff

* remove overly defensive programming

* update type check

* type more code

* remove more dead code

* address bugbot comments

* fix(security): restrict API key access on internal-only routes (#2964)

* fix(security): restrict API key access on internal-only routes

* test(security): update function execute tests for checkInternalAuth

* updated agent handler

* move session check higher in checkSessionOrInternalAuth

* extracted duplicate code into helper for resolving user from jwt

* fix(copilot): update copilot chat title (#2968)

* fix(hitl): fix condition blocks after hitl (#2967)

* fix(notes): ghost edges (#2970)

* fix(notes): ghost edges

* fix deployed state fallback

* fallback

* remove UI level checks

* annotation missing from autoconnect source check

* improvement(docs): loop and parallel var reference syntax (#2975)

* fix(blog): slash actions description (#2976)

* improvement(docs): loop and parallel var reference syntax

* fix(blog): slash actions description

* fix(auth): copilot routes (#2977)

* Fix copilot auth

* Fix

* Fix

* Fix

* fix(copilot): fix edit summary for loops/parallels (#2978)

* fix(integrations): hide from tool bar (#2544)

* fix(landing): ui (#2979)

* fix(edge-validation): race condition on collaborative add (#2980)

* fix(variables): boolean type support and input improvements (#2981)

* fix(variables): boolean type support and input improvements

* fix formatting

---------

Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com>
Co-authored-by: Emir Karabeg <78010029+emir-karabeg@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Siddharth Ganesan <33737564+Sg312@users.noreply.github.com>
Co-authored-by: Vikhyath Mondreti <vikhyath@simstudio.ai>
waleedlatif1 added a commit that referenced this pull request Jan 24, 2026
…2973)

* fix(subflows): tag dropdown + resolution logic (#2949)

* fix(subflows): tag dropdown + resolution logic

* fixes;

* revert parallel change

* chore(deps): bump posthog-js to 1.334.1 (#2948)

* fix(idempotency): add conflict target to atomicallyClaimDb query + remove redundant db namespace tracking (#2950)

* fix(idempotency): add conflict target to atomicallyClaimDb query

* delete needs to account for namespace

* simplify namespace filtering logic

* fix cleanup

* consistent target

* improvement(kb): add document filtering, select all, and React Query migration (#2951)

* improvement(kb): add document filtering, select all, and React Query migration

* test(kb): update tests for enabledFilter and removed userId params

* fix(kb): remove non-null assertion, add explicit guard

* improvement(logs): trace span, details (#2952)

* improvement(action-bar): ordering

* improvement(logs): details, trace span

* feat(blog): v0.5 release post (#2953)

* feat(blog): v0.5 post

* improvement(blog): simplify title and remove code block header

- Simplified blog title from Introducing Sim Studio v0.5 to Introducing Sim v0.5
- Removed language label header and copy button from code blocks for cleaner appearance

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* ack PR comments

* small styling improvements

* created system to create post-specific components

* updated componnet

* cache invalidation

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* feat(admin): add credits endpoint to issue credits to users (#2954)

* feat(admin): add credits endpoint to issue credits to users

* fix(admin): use existing credit functions and handle enterprise seats

* fix(admin): reject NaN and Infinity in amount validation

* styling

* fix(admin): validate userId and email are strings

* improvement(copilot): fast mode, subagent tool responses and allow preferences (#2955)

* Improvements

* Fix actions mapping

* Remove console logs

* fix(billing): handle missing userStats and prevent crashes (#2956)

* fix(billing): handle missing userStats and prevent crashes

* fix(billing): correct import path for getFilledPillColor

* fix(billing): add Number.isFinite check to lastPeriodCost

* fix(logs): refresh logic to refresh logs details (#2958)

* fix(security): add authentication and input validation to API routes (#2959)

* fix(security): add authentication and input validation to API routes

* moved utils

* remove extraneous commetns

* removed unused dep

* improvement(helm): add internal ingress support and same-host path consolidation (#2960)

* improvement(helm): add internal ingress support and same-host path consolidation

* improvement(helm): clean up ingress template comments

Simplify verbose inline Helm comments and section dividers to match the
minimal style used in services.yaml.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix(helm): add missing copilot path consolidation for realtime host

When copilot.host equals realtime.host but differs from app.host,
copilot paths were not being routed. Added logic to consolidate
copilot paths into the realtime rule for this scenario.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* improvement(helm): follow ingress best practices

- Remove orphan comments that appeared when services were disabled
- Add documentation about path ordering requirements
- Paths rendered in order: realtime, copilot, app (specific before catch-all)
- Clean template output matching industry Helm chart standards

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* feat(blog): enterprise post (#2961)

* feat(blog): enterprise post

* added more images, styling

* more content

* updated v0-5 post

* remove unused transition

---------

Co-authored-by: Vikhyath Mondreti <vikhyath@simstudio.ai>

* fix(envvars): resolution standardized (#2957)

* fix(envvars): resolution standardized

* remove comments

* address bugbot

* fix highlighting for env vars

* remove comments

* address greptile

* address bugbot

* fix(copilot): mask credentials fix (#2963)

* Fix copilot masking

* Clean up

* Lint

* improvement(webhooks): remove dead code (#2965)

* fix(webhooks): subscription recreation path

* improvement(webhooks): remove dead code

* fix tests

* address bugbot comments

* fix restoration edge case

* fix more edge cases

* address bugbot comments

* fix gmail polling

* add warnings for UI indication for credential sets

* fix(preview): subblock values (#2969)

* fix(child-workflow): nested spans handoff (#2966)

* fix(child-workflow): nested spans handoff

* remove overly defensive programming

* update type check

* type more code

* remove more dead code

* address bugbot comments

* fix(security): restrict API key access on internal-only routes (#2964)

* fix(security): restrict API key access on internal-only routes

* test(security): update function execute tests for checkInternalAuth

* updated agent handler

* move session check higher in checkSessionOrInternalAuth

* extracted duplicate code into helper for resolving user from jwt

* fix(copilot): update copilot chat title (#2968)

* fix(hitl): fix condition blocks after hitl (#2967)

* fix(notes): ghost edges (#2970)

* fix(notes): ghost edges

* fix deployed state fallback

* fallback

* remove UI level checks

* annotation missing from autoconnect source check

* improvement(docs): loop and parallel var reference syntax (#2975)

* fix(blog): slash actions description (#2976)

* improvement(docs): loop and parallel var reference syntax

* fix(blog): slash actions description

* fix(auth): copilot routes (#2977)

* Fix copilot auth

* Fix

* Fix

* Fix

* fix(copilot): fix edit summary for loops/parallels (#2978)

* fix(integrations): hide from tool bar (#2544)

* fix(landing): ui (#2979)

* fix(edge-validation): race condition on collaborative add (#2980)

* fix(variables): boolean type support and input improvements (#2981)

* fix(variables): boolean type support and input improvements

* fix formatting

---------

Co-authored-by: Vikhyath Mondreti <vikhyathvikku@gmail.com>
Co-authored-by: Emir Karabeg <78010029+emir-karabeg@users.noreply.github.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: Siddharth Ganesan <33737564+Sg312@users.noreply.github.com>
Co-authored-by: Vikhyath Mondreti <vikhyath@simstudio.ai>
@waleedlatif1 waleedlatif1 deleted the fix/edge-validation-race branch January 25, 2026 05:14
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants